/*
 * DIM-SUM操作系统 -- 初始入口文件
 *
 * Copyright (C) 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Dong Peng <w-pengdong@kernelsoft.com>
 *			Lei Ding <dinglei@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <dim-sum/linkage.h>
#include <asm/cache.h>
#include <asm/memory.h>
#include <asm/page.h>
#include <asm/asm-offsets.h>
#include <asm/csr.h>
#include <asm/asm.h>
#include "image.h"

.section	".head.text","ax"
ENTRY(kernel_text_start)
	/* jump to start kernel */
	j _start_kernel
	/* reserved */
	.word 0
	.balign 8
	.dword 0x200000
	/* Effective size of kernel image */
	.dword kernel_text_end - kernel_text_start
	.dword __HEAD_FLAGS
	.word RISCV_HEADER_VERSION
	.word 0
	.dword 0
	.ascii RISCV_IMAGE_MAGIC
	.balign 4
	.ascii RISCV_IMAGE_MAGIC2
END(kernel_text_start)

ENTRY(_start_kernel)
	/* 关闭全部中断 */
	csrw CSR_IE, zero
	csrw CSR_IP, zero

	/*加载全局指针*/
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/*
	 * 关闭FPU
	 */
	li t0, SR_FS
	csrc CSR_STATUS, t0

	/* 选择一个运行主启动程序的 hart */
	la a3, hart_lottery
	li a2, 1
	amoadd.w a3, a2, (a3)
	bnez a3, slave_cpu_entry

	/* 清零BSS段 */
	la a3, __bss_start
	la a4, __bss_stop
	ble a4, a3, clear_bss_done
clear_bss:
	STORE_REG zero, (a3)
	add a3, a3, RISCV_SZPTR
	blt a3, a4, clear_bss
clear_bss_done:

	/* 保存hartID和DTB物理地址 */
	mv s0, a0
	mv s1, a1
	la a2, boot_cpu_hartid
	STORE_REG a0, (a2)

	/* 初始化栈 */
	la sp, init_stack_end
	call create_start_mmutbl
	la a0, pgtbl_root
	call mmu_enable

	/* 使用初始化进程的栈 */
	la sp, init_stack_end
	/* Start the kernel */
	mv a0, s0
	mv a1, s1
	call parse_dtb
	tail start_master

mmu_enable:
	/* 计算mmu_enable返回的虚拟地址 */
	li a1, KERNEL_VA_START
	la a2, kernel_text_start
	sub a1, a1, a2
	add ra, ra, a1

	la a2, 1f
	add a2, a2, a1
	csrw CSR_TVEC, a2

	/* 计算并加载内核页表 */
	srl a2, a0, PAGE_SHIFT
	li a1, SATP_MODE
	or a2, a2, a1

	/*
	 * 加载跳板页表
	 */
	la a0, trampoline_pg_dir
	srl a0, a0, PAGE_SHIFT
	or a0, a0, a1
	sfence.vma
	csrw CSR_SATP, a0
.align 2
1:
	/* 设置自旋陷入向量表有助于调试 */
	la a0, .spin_wait
	csrw CSR_TVEC, a0

	/* 重新加载全局指针 */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/*
	 * 切换内核页表
	 */
	csrw CSR_SATP, a2
	sfence.vma

	ret
END(_start_kernel)

.section	".head.text","ax"
ENTRY(slave_cpu_entry)
#ifdef CONFIG_SMP
	/* 关闭全部中断 */
	csrw CSR_IE, zero
	csrw CSR_IP, zero

	/*加载全局指针*/
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/*
	 * 关闭FPU
	 */
	li t0, SR_FS
	csrc CSR_STATUS, t0

	/*设置自旋陷入向量表有助于调试*/
	la a3, .spin_wait
	csrw CSR_TVEC, a3

	slli a3, a0, LGREG
	la a4, __cpu_up_stack_pointer
	la a5, __cpu_up_task_pointer
	add a4, a3, a4
	add a5, a3, a5
	LOAD_REG sp, (a4)
	LOAD_REG tp, (a5)
	la a0, pgtbl_root
	call mmu_enable
	la a0, slave_cpu_data
	tail start_slave
#endif

.align 2
.spin_wait:
	wfi
	j .spin_wait
END(slave_cpu_entry)
